package de.unikoblenz.west.csxpoi.server;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.openrdf.query.BindingSet;
import org.openrdf.query.MalformedQueryException;
import org.openrdf.query.QueryEvaluationException;
import org.openrdf.query.QueryLanguage;
import org.openrdf.query.TupleQuery;
import org.openrdf.query.TupleQueryResult;
import org.openrdf.repository.RepositoryConnection;
import org.openrdf.repository.RepositoryException;

/**
 * Encapsulates users, which are identified by their URI and have a username, a
 * full name, and an email address.
 * 
 */
public class UserWrapper {

	/**
	 * the URI of the user
	 */
	private String mUri = null;

	/**
	 * the username of the user
	 */
	private String mUsername = null;

	/**
	 * the full name of the user
	 */
	private String mName = null;

	/**
	 * the email address of the user
	 */
	private String mEmail = null;

	/**
	 * Creates a user from the specified username by retrieving all properties
	 * from the repository.
	 * 
	 * @param username
	 *            the username of the user to create
	 * @param password
	 *            the password of the user to create
	 * @param connection
	 *            a repository connection
	 * @return a user with the specified username and the retrieved properties
	 *         or null if the creation failed
	 * @throws QueryEvaluationException
	 * @throws RepositoryException
	 * @throws MalformedQueryException
	 */
	public static UserWrapper createFromUsername(String username,
			String password, RepositoryConnection connection)
			throws QueryEvaluationException, RepositoryException,
			MalformedQueryException {

		UserWrapper user = null;

		TupleQuery query = connection.prepareTupleQuery(QueryLanguage.SPARQL,
				"PREFIX base: <" + Constants.NS_BASE + "> " + "PREFIX foaf: <"
						+ Constants.NS_FOAF + "> " + "PREFIX xsd: <"
						+ Constants.NS_XSD + "> "
						+ "SELECT ?user ?name ?email WHERE {"
						+ " ?user a base:User ;" + "  foaf:nick ?username ;"
						+ "  base:password ?password ."
						+ " OPTIONAL { ?user foaf:name ?name }"
						+ " OPTIONAL { ?user foaf:mbox ?email }"
						+ " FILTER (str(?username) = \"" + username + "\")"
						+ " FILTER (str(?password) = \"" + password + "\")"
						+ "} LIMIT 1");
		TupleQueryResult result = query.evaluate();
		try {
			if (result.hasNext()) {
				BindingSet bindingSet = result.next();
				user = new UserWrapper();
				user.setUri(bindingSet.getValue("user").stringValue());
				user.setUsername(username);
				if (bindingSet.hasBinding("name")) {
					user.setName(bindingSet.getValue("name").stringValue());
				}
				if (bindingSet.hasBinding("email")) {
					String mailto = bindingSet.getValue("email").stringValue();
					Pattern mailtoPattern = Pattern.compile("^mailto:(.*)$");
					Matcher mailtoMatcher = mailtoPattern.matcher(mailto);
					if (mailtoMatcher.find()) {
						user.setEmail(mailtoMatcher.group(1));
					}
				}
			}
		} finally {
			result.close();
		}

		return user;

	}

	/**
	 * Gets the URI of the user.
	 * 
	 * @return the URI of the user
	 */
	public String getUri() {
		return mUri;
	}

	/**
	 * Gets the username of the user.
	 * 
	 * @return the username of the user
	 */
	public String getUsername() {
		return mUsername;
	}

	/**
	 * Gets the full name of the user.
	 * 
	 * @return the full name of the user
	 */
	public String getName() {
		return mName;
	}

	/**
	 * Gets the email address of the user.
	 * 
	 * @return the email address of the user
	 */
	public String getEmail() {
		return mEmail;
	}

	/**
	 * Sets the URI of the user.
	 * 
	 * @param uri
	 *            the URI to set
	 */
	public void setUri(String uri) {
		mUri = uri;
	}

	/**
	 * Sets the full name of the user.
	 * 
	 * @param name
	 *            the full name to set
	 */
	public void setName(String name) {
		mName = name;
	}

	/**
	 * Sets the username of the user.
	 * 
	 * @param username
	 *            the username to set
	 */
	public void setUsername(String username) {
		mUsername = username;
	}

	/**
	 * Sets the email address of the user.
	 * 
	 * @param email
	 *            the email address to set
	 */
	public void setEmail(String email) {
		mEmail = email;
	}

}
